﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Encloser.Json
{
    public class JsonObject : JsonItem, IDictionary<string, JsonItem>, ICollection<KeyValuePair<string, JsonItem>>, IEnumerable<KeyValuePair<string, JsonItem>>, IEnumerable, IDictionary, ICollection
    {
        private readonly Dictionary<string, JsonItem> keyValuePairs = new Dictionary<string, JsonItem>();
        internal override object Value { get => keyValuePairs; }
        public JsonObject() : base(JsonType.Object) { }
        public JsonItem this[string key] 
        { 
            get
            {
                if (string.IsNullOrEmpty(key) || !keyValuePairs.TryGetValue(key, out JsonItem val)) return null;
                return val;
            }
            set
            {
                if (string.IsNullOrEmpty(key)) return;
                if (keyValuePairs.ContainsKey(key)) keyValuePairs[key] = value;
                else keyValuePairs.Add(key, value);
            }
        }
        public ICollection<string> Keys => keyValuePairs.Keys;
        public ICollection<JsonItem> Values => keyValuePairs.Values;
        public int Count => keyValuePairs.Count;
        public object this[object key]
        { 
            get => this[key?.ToString()]; 
            set 
            {
                var k = key?.ToString();
                if (string.IsNullOrEmpty(k)) return;
                if (value == null) this[k] = null;
                else if (value is JsonItem) this[k] = value as JsonItem;
                else JsonParser.ToJsonItem(value).Try(val => this[k] = val);
            }
        }
        ICollection IDictionary.Keys => keyValuePairs.Keys;
        ICollection IDictionary.Values => keyValuePairs.Values;
        bool ICollection<KeyValuePair<string, JsonItem>>.IsReadOnly => false;
        bool IDictionary.IsReadOnly => false;
        bool IDictionary.IsFixedSize => false;
        object ICollection.SyncRoot => this;
        bool ICollection.IsSynchronized => false;
        bool IDictionary.Contains(object key) => ContainsKey(key?.ToString());
        void ICollection<KeyValuePair<string, JsonItem>>.CopyTo(KeyValuePair<string, JsonItem>[] array, int arrayIndex) 
            => (keyValuePairs as ICollection<KeyValuePair<string, JsonItem>>).CopyTo(array, arrayIndex);
        void ICollection.CopyTo(Array array, int index) => (keyValuePairs as ICollection).CopyTo(array, index);
        void IDictionary.Remove(object key) => Remove(key?.ToString()); 
        bool ICollection<KeyValuePair<string, JsonItem>>.Remove(KeyValuePair<string, JsonItem> item) => Remove(item.Key); 
        IEnumerator IEnumerable.GetEnumerator() => keyValuePairs.GetEnumerator(); 
        IDictionaryEnumerator IDictionary.GetEnumerator() => keyValuePairs.GetEnumerator(); 
        public void Add(string key, JsonItem value) => this[key] = value; 
        public void Add(object key, object value) => this[key] = value; 
        public void Add(KeyValuePair<string, JsonItem> item) => this[item.Key] = item.Value; 
        public void Clear() => keyValuePairs.Clear(); 
        public bool Contains(KeyValuePair<string, JsonItem> item) => item.Key != null && keyValuePairs.Contains(item); 
        public bool ContainsKey(string key) => key != null && keyValuePairs.ContainsKey(key); 
        public IEnumerator<KeyValuePair<string, JsonItem>> GetEnumerator() => keyValuePairs.GetEnumerator(); 
        public bool Remove(string key) => key != null && keyValuePairs.Remove(key);
        public bool TryGetValue(string key, out JsonItem value) { value = null; return key != null && keyValuePairs.TryGetValue(key, out value); }
    }
}
